package com.chainyoung.common.base;

import android.app.Application;
import android.util.Log;

import com.alibaba.android.arouter.launcher.ARouter;
import com.chainyoung.common.BuildConfig;
import com.chainyoung.common.R;
import com.chainyoung.common.common_widget.loadsir.core.LoadSir;
import com.chainyoung.common.constant.LibConstant;
import com.chainyoung.common.custom_widget.EmptyCallback;
import com.chainyoung.common.custom_widget.EmptyCollectionCallback;
import com.chainyoung.common.custom_widget.LoadingCallback;
import com.chainyoung.common.custom_widget.PlaceholderCallback;
import com.chainyoung.common.custom_widget.RetryCallback;
import com.chainyoung.common.di.AppComponent;
import com.chainyoung.common.di.DaggerAppComponent;
import com.chainyoung.common.di.module.AppModule;
import com.chainyoung.common.di.module.ClientModule;
import com.chainyoung.common.di.module.GlobeConfigModule;
import com.chainyoung.common.di.module.ImageModule;
import com.chainyoung.common.exception.CrashHandler;
import com.chainyoung.common.http.interceptor.MyHttpLoggerIntercept;
import com.chainyoung.common.http.interceptor.PhoneInfoInterceptor;
import com.chainyoung.common.http.websocket.WebSoketUtils;
import com.chainyoung.common.http.websocket.WsManager;
import com.chainyoung.common.integration.ActivityLifecycle;
import com.chainyoung.common.integration.ConfigModule;
import com.chainyoung.common.integration.ManifestParser;
import com.chainyoung.common.utils.LogUtils;
import com.chainyoung.common.utils.SPUtil;
import com.chainyoung.common.utils.ToastUtil;
import com.chainyoung.common.utils.Utils;
import com.tencent.smtt.sdk.QbSdk;
import com.umeng.commonsdk.UMConfigure;


import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import cn.jpush.android.api.JPushInterface;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;
import io.realm.Realm;
//import io.realm.Realm;

/**
 * Common Application的生命周期代理
 */

public class CommonApplicationLike implements IApplicationLike {

    static {
        //Umeng Share各个平台的配置
//    PlatformConfig.setWeixin(BuildConfig.WEIXIN_ID, BuildConfig.WEIXIN_KEY);
//    PlatformConfig.setSinaWeibo(BuildConfig.SINA_WEIBO_KEY, BuildConfig.SINA_WEIBO_SECRET,
//        "http://sns.whalecloud.com");
//    PlatformConfig.setQQZone(BuildConfig.QQ_ZONE_ID, BuildConfig.QQ_ZONE_KEY);
    }

    private final List<ConfigModule> mModules;
    @Inject
    protected ActivityLifecycle mActivityLifecycle;
    private Application mApplication;
    private AppComponent mAppComponent;
    private List<Lifecycle> mLifecycles = new ArrayList<>();
    //private RefWatcher mRefWatcher;//leakCanary观察器

    private WsManager wsManager;

    public CommonApplicationLike(Application application) {
        this.mApplication = application;
        this.mModules = new ManifestParser(mApplication).parse();
        for (ConfigModule module : mModules) {
            module.injectAppLifecycle(mApplication, mLifecycles);
        }
    }

    @Override
    public void onCreate() {
        mAppComponent = DaggerAppComponent
                .builder()
                .appModule(new AppModule(mApplication))////提供application
                .clientModule(new ClientModule())//用于提供okhttp和retrofit的单例
                .imageModule(new ImageModule())//图片加载框架默认使用glide
                .globeConfigModule(getGlobeConfigModule(mApplication, mModules))//全局配置
                .build();
        mAppComponent.inject(this);
        Utils.initAppComponent(mAppComponent);


        //router
        if (BuildConfig.DEBUG) {
            ARouter.openLog();
            ARouter.openDebug();
            ARouter.printStackTrace();
        }
        ARouter.init(mApplication);

        //db init
        Realm.init(mApplication);

        //init utils
        Utils.init(mApplication);

        initCrashHandler();
        initTools();//初始化工具类

        //log
        // LogUtil.init(BuildConfig.DEBUG);


        //loadsir init
        LoadSir.beginBuilder()
                .addCallback(new LoadingCallback())
                .addCallback(new EmptyCallback())
                .addCallback(new EmptyCollectionCallback())
                .addCallback(new PlaceholderCallback())
                .addCallback(new RetryCallback())
                .setDefaultCallback(LoadingCallback.class)
                .commit();

        mApplication.registerActivityLifecycleCallbacks(mActivityLifecycle);

        for (ConfigModule module : mModules) {
            module.registerComponents(mApplication, mAppComponent.repositoryManager());
        }

        for (Lifecycle lifecycle : mLifecycles) {
            lifecycle.onCreate(mApplication);
        }


        //leakCanary内存泄露检查
        installLeakCanary();

        //rx全局异常处理
        setRxJavaErrorHandler();

        //websocket manager
        WebSoketUtils.init(mApplication.getApplicationContext());

        //友盟统计
        UMConfigure.init(mApplication.getApplicationContext(), "5bbf4b8eb465f51a2c0001ff", null, UMConfigure.DEVICE_TYPE_PHONE, null);

    }

    private void initCrashHandler() {
        CrashHandler crashHandler = CrashHandler.getInstance();
        crashHandler.init(mApplication.getApplicationContext());
    }


    private void initTools() {
        ToastUtil.init(mApplication.getApplicationContext());
        SPUtil.init(mApplication.getApplicationContext());
    }

    /**
     * RxJava2 当取消订阅后(dispose())，RxJava抛出的异常后续无法接收(此时后台线程仍在跑，可能会抛出IO等异常),全部由RxJavaPlugin接收，需要提前设置ErrorHandler
     * 详情：http://engineering.rallyhealth.com/mobile/rxjava/reactive/2017/03/15/migrating-to-rxjava-2.html#Error
     * Handling
     */
    private void setRxJavaErrorHandler() {
        RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                // LogUtils.d("setRxJavaErrorHandler:");
                throwable.printStackTrace();
            }
        });
    }

    public void onDefaultProcessCreate() {
        recordVersionCode();
        initToastyConfig();
        initX5Web();
        initUShare();
        initJPush();
    }

    /**
     * 记录app版本号
     * 可以通过这个记录后期做一些新旧版本切换埋点和额外操作
     */
    private void recordVersionCode() {
//    int hisVerion = SPUtils.getInstance().getInt(SPConstants.APP_VERSION_CODE, -1);
//    int curVersion = BuildConfig.appVerCode;
//    if (hisVerion != curVersion) {
//      SPUtils.getInstance().put(SPConstants.APP_VERSION_CODE, curVersion);
//    }
    }

    public void onTerminate() {
        if (mActivityLifecycle != null) {
            mApplication.unregisterActivityLifecycleCallbacks(mActivityLifecycle);
        }
        this.mAppComponent = null;
        this.mActivityLifecycle = null;
        this.mApplication = null;

        for (Lifecycle lifecycle : mLifecycles) {
            lifecycle.onTerminate(mApplication);
        }

//    if (mRefWatcher != null) {
//      this.mRefWatcher = null;
//    }
    }

    private void initJPush(){
        JPushInterface.setDebugMode(BuildConfig.DEBUG); 	// 设置开启日志,发布时请关闭日志
        JPushInterface.init(mApplication.getApplicationContext());
    }

    //Umeng Share
    private void initUShare() {
//    Config.DEBUG = BuildConfig.DEBUG;
//    QueuedWork.isUseThreadPool = false;
//    UMShareAPI.init(mApplication, BuildConfig.UMENG_APP_KEY);
    }

    private void initToastyConfig() {
    /*Toasty.Config.getInstance()
        .setErrorColor( @ColorInt int errorColor) // optional
    .setInfoColor( @ColorInt int infoColor) // optional
    .setSuccessColor( @ColorInt int successColor) // optional
    .setWarningColor( @ColorInt int warningColor) // optional
    .setTextColor( @ColorInt int textColor) // optional
    .tintIcon( boolean tintIcon) // optional (apply textColor also to the icon)
    .setToastTypeface(@NonNull Typeface typeface) // optional
        .apply(); */
    }

    private void initX5Web() {

        QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

            @Override
            public void onViewInitFinished(boolean arg0) {
                // TODO Auto-generated method stub
                //x5內核初始化完成的回调，为true表示x5内核加载成功，否则表示x5内核加载失败，会自动切换到系统内核。
                Log.d("app", " onViewInitFinished is " + arg0);
            }

            @Override
            public void onCoreInitFinished() {
                // TODO Auto-generated method stub
            }
        };
        //x5内核初始化接口
        QbSdk.initX5Environment(mApplication.getApplicationContext(), cb);
    }

    /**
     * 安装leakCanary检测内存泄露
     */
    protected void installLeakCanary() {
        // this.mRefWatcher = BuildConfig.DEBUG ? LeakCanary.install(mApplication) : RefWatcher.DISABLED;
    }


    /**
     * 将app的全局配置信息封装进module(使用Dagger注入到需要配置信息的地方)
     * 需要在AndroidManifest中声明{@link ConfigModule}的实现类,和Glide的配置方式相似
     */
    private GlobeConfigModule getGlobeConfigModule(Application context, List<ConfigModule> modules) {

        GlobeConfigModule.Builder builder = GlobeConfigModule
                .builder()
                .baseurl(LibConstant.BASE_URL)//为了防止用户没有通过GlobeConfigModule配置baseurl,而导致报错,所以提前配置个默认baseurl
                .addInterceptor(new PhoneInfoInterceptor(mApplication.getApplicationContext()))
//                .addInterceptor(new ReceivedCookiesInterceptor())
//                .addInterceptor(new AddCookiesInterceptor())
                .addInterceptor(new MyHttpLoggerIntercept())
                .statusBarColor(R.color._4486f5);  //提供一个默认的状态栏颜色
        // .statusBarAlpha(255);

        for (ConfigModule module : modules) {
            module.applyOptions(context, builder);
        }

        return builder.build();
    }

    public interface Lifecycle {

        void onCreate(Application application);

        void onTerminate(Application application);
    }

}